#include "subscriber_manager.hpp"
#include <sstream>
#include <boost/uuid/uuid_io.hpp>
#include "subscription_container.hpp"
#include "channels_container.hpp"
#include "subscribe_channel_container.hpp"

namespace fasys{



subscriber_manager::~subscriber_manager()
{
};

subscriber_manager::subscriber_manager()
  : _ran(), _gen( &_ran )
  , _subscriptions(new subscription_container)
  , _channels_container(new channels_container)
  , _subscription_couner(0)
  , _channels ( new subscribe_channel_container)
  , _channels_manager(0)
{
  _ran.seed(time(0));
}

  // проверяет есть ли сообщения в подписке
bool subscriber_manager::has_messages(const std::string& key, const std::string& uuid)
{
/*  if ( subscription* s = _subscriptions->find(key, uuid) )
  {
  };
  */
  return bool();
}

// вызывать только полсе того, как выгребуться все сообщения из подписки 
void subscriber_manager::subscribe(const std::string& key, const std::string& uuid, isubscriber* observer)
{
  _subscriptions->subscribe(key, uuid, observer);
}

void subscriber_manager::describe(const std::string& key, const std::string& uuid, isubscriber* observer)
{
  _subscriptions->describe(key, uuid, observer);
}


struct f_publish
{
  const message& m;
  f_publish(const message& m): m(m){}
  void operator()(const subscribe_channel& sc)
  {
    if (sc.subject->observer)
      sc.subject->observer->published(m);
    else
      sc.subject->republish(m);
  }
};
void subscriber_manager::publish(const message& m)
{
  std::cout << "void subscriber_manager::publish(const message& m)" << std::endl;
  _channels->for_each(m.channel_id, f_publish(m) );
}

std::string subscriber_manager::create( const std::string& key, time_t lifetime,  const channel_list& cl)
{
  using namespace ::boost;
  using namespace ::boost::uuids;

  subscribe_id_t subscribe_id = ++_subscription_couner;
  subscription* s = new subscription(_channels_container);
  _subscription_map.insert( std::make_pair(subscribe_id, s) );
  subscription_info info;
  std::stringstream ss;
  ss << _gen();
  info.uuid = ss.str();
  info.key = key;
  info.subscribe_id = subscribe_id;
  info.lifetime = lifetime;
  info.subject = s;
  _subscriptions->insert(info);

  channel_list::const_iterator itr = cl.begin();
  for ( ;itr!=cl.end(); ++itr)
  {
    channel_id_t channel_id = s->create(itr->channel, itr->min_size, itr->min_size);
    _channels->insert(subscribe_id, channel_id, s);
    if ( _channels_manager )
      _channels_manager->subscribe(itr->channel, this);
  }
  return info.uuid;
}

void subscriber_manager::move_messages(const std::string& key, const std::string& uuid, std::list<message>& ml )
{
  _subscriptions->move_messages(key, uuid, ml);
}

/*
void subscriber_manager::publish(const message_notify& cmd)
{
}

void subscriber_manager::publish(const message_list_response& cmd)
{
}

void subscriber_manager::create_subscription(create_subscription_request& request, create_subscription_response& response)
{
  using namespace ::boost;
  using namespace ::boost::uuids;
  std::stringstream ss;
  ss << _gen();
  response.subscribe_uuid = ss.str();
  
}
*/

}

